#![allow(unused_assignments)]
#![allow(dead_code)]
#![allow(non_snake_case)]
use core::mem::size_of;

#[repr(C)]
struct ExceptionStackFrame
{
    r0 :u32,
    r1 :u32,
    r2 :u32,
    r3 :u32,
    r12:u32,
    lr :u32,
    pc :u32,
    psr:u32,
}

struct StackFrame
{
    r4 :u32,
    r5 :u32,
    r6 :u32,
    r7 :u32,
    r8 :u32,
    r9 :u32,
    r10:u32,
    r11:u32,
    exception_stack_frame: ExceptionStackFrame
}

#[no_mangle]
pub static rt_interrupt_from_thread: u32 = 0;
#[no_mangle]
pub static rt_interrupt_to_thread: u32 = 0;
#[no_mangle]
pub static rt_thread_switch_interrupt_flag: u32 = 0;

pub fn rt_hw_stack_init(entry: u32, param: u32, stack_address: u32, exit: u32) -> u32 {
    let mut stack_frame: *mut StackFrame = 0 as _;
    let mut stk = 0u32;

    stk = stack_address + 4;

    // 8字节对齐
    stk |= !0b111u32;
    // 开拓出空间
    stk -= size_of::<StackFrame>() as u32;
    stack_frame = stk as _;

    unsafe {
        (*stack_frame).exception_stack_frame.r0 = param;
        (*stack_frame).exception_stack_frame.r1 = 0;
        (*stack_frame).exception_stack_frame.r2 = 0;
        (*stack_frame).exception_stack_frame.r3 = 0;
        (*stack_frame).exception_stack_frame.r12 = 0;
        (*stack_frame).exception_stack_frame.lr = exit;
        (*stack_frame).exception_stack_frame.pc = entry;
        (*stack_frame).exception_stack_frame.psr = 0x01000000;
    }

    stk
}

pub fn rt_context_switch(from_sp: u32, to_sp: u32) {
    unsafe {
        rt_hw_context_switch(from_sp, to_sp);
    }
}

pub fn rt_context_switch_to(to_sp: u32) {
    unsafe {
        rt_hw_context_switch_to(to_sp);
    }
}

#[link(name="context")]
extern "C" {
    fn rt_hw_context_switch(from_sp: u32, to_sp: u32);
    fn rt_hw_context_switch_to(to_sp: u32);
    fn PendSV_Handler();
}

use cortex_m_rt::exception;

#[exception]
unsafe fn PendSV() {
    PendSV_Handler()
}
